package HSCHoSEPlainChannel;
use strict;
use vars qw /@ISA/;
use Data::Dumper;
use Date::Manip;
use LWP::UserAgent;
use POSIX qw(strftime);
use StockInfoSet;
use StockInfo;
use MarketInfo;
use ChannelInfo; 
use DataCollectionChannel;
@ISA = ("DataCollectionChannel");

sub new{
	my $class = shift;
	my $self = {};
	$self->{URL} = 'http://priceonline.hsc.com.vn/Process.aspx?Type=S&Page=0';
	$self->{STOCK_FIELD_FORMAT} = [ 'Symbol', 'RefPrice', 'CeilingPrice', 'FloorPrice', '', 
									'HighestPrice', 'LowestPrice', 'TempPrice', 'ChangedPrice', 'TempVolume',
									'Best3BidPrice', 'Best3BidVolume', 'Best2BidPrice', 'Best2BidVolume', 'Best1BidPrice', 'Best1BidVolume',
									'Best1OffPrice', 'Best1OffVolume', 'Best2OffPrice', 'Best2OffVolume','Best3OffPrice', 'Best3OffVolume', 	
									'SS1MatchPrice', 'SS1MatchVolume', 'SS2MatchVolume', '', '', 'SS2MatchPrice', '',								
									'FRoom', 'FBuy', 'Description' ];
									
	$self->{MARKET_FIELD_FORMAT} = [ 'SessionNo', 'Index', 'ChangeIndex', 'TotalVolume', 'TotalValue', 'Transactions', 'ChangePercent', 'Advances', 
									 'NoChange' , 'Declines', 'TradingDate', 'Time', 'NP_V', 'NV_V', 'PrevIndex'];

	$self->{SECURITY_CENTER_CODE} = 'HoSE';
	bless $self, $class;
	return $self;
}

##################################
##	get html page of given url	##
##################################
sub get_data_source{
	my $self = shift;
	my $browser = LWP::UserAgent->new(
	  	agent => 'Mozilla/5.0 (compatible; MSIE 4.01; Windows95)',
	  	timeout =>	$self->{TIMEOUT} 	
	);	
	$browser->parse_head(0);	  
 	my $resp = $browser->get($self->{URL});
 	return ($resp->content, $resp->is_success, $resp->status_line);   	
}

##################################
## get stock info set			##
## input:						##
## output:						##
##		a StockInfoSet object	##
##################################
sub get_stock_info_set{
	my $self = shift;
	my $content;
	my $is_success;
	my $status_line;
	my $proc_time;
	my $channel_name = 	$self->{NAME};
	my $start_time = time();
	my $stock_info_set = StockInfoSet::new();
	
	# assign sys sequence, start_time and name to channelinfo object
	$stock_info_set->{CHANNEL_INFO}->set('SYS_SEQ', shift);
	$stock_info_set->{CHANNEL_INFO}->set('NAME', $channel_name);
	$stock_info_set->{CHANNEL_INFO}->set('START_TIME', $start_time);
	# assign priority
	$stock_info_set->{MARKET_INFO}->set('PRIORITY', $self->{PRIORITY});
	
	
	# get data source from url	
	($content, $is_success, $status_line) = $self->get_data_source();
	
	if (!$is_success){
		$self->{STATUS}->{CODE} = 'TIMEOUT';
		$self->{STATUS}->{MSG} = 'Can\'t fetch data source(connection timeout)';
		# caculate processing time 
		$proc_time = time - $start_time;
		$stock_info_set->{CHANNEL_INFO}->set('PROCESSING_TIME', $proc_time);
		$stock_info_set->{CHANNEL_INFO}->set('STATUS', $self->{STATUS}->{CODE});
		$stock_info_set->{CHANNEL_INFO}->set('MESSAGE', $self->{STATUS}->{MSG});
		$stock_info_set->{MARKET_INFO} = undef;
		$stock_info_set->stock_infos(undef);
		return ($stock_info_set,$self->{STATUS});			
	}else{
		$self->{STATUS}->{CODE} = 'OK';
		$self->{STATUS}->{MSG} = "Data source is fetched($status_line)";					
	}
	
	# got the content, parse it to get market_info and stock_info set
	if( $content =~ /(.*)\%\^(.*)/ ){ # the content is in a valid format
		my $content_market_info = $1;
		my $content_stock_info = $2;
		my @market_infos = split(':', $content_market_info);
		for(my $i=0; $i < @{$self->{MARKET_FIELD_FORMAT}}; $i++){
			my $field = @{$self->{MARKET_FIELD_FORMAT}}[$i];
			if($i < @market_infos ){				
				my $field_value = $market_infos[$i];
				$field_value = 0 if($field_value eq '');
				$field_value =~ s/,//g;
				if($field eq 'TotalValue'){ $field_value /= 1000000000 } # calculate by billion units
				$stock_info_set->{MARKET_INFO}->set($field, $field_value);
			}else{
				$stock_info_set->{MARKET_INFO}->set($field, undef);
			}
		}
		# set market date
		$stock_info_set->{MARKET_INFO}->set('TradingDate', strftime("%d/%m/%Y", localtime($stock_info_set->start_time())));
		# set market time based on the delay time
		if($self->{DELAY_TIME}){ 
			my $market_time = DateCalc(ParseDate("today"), "- " . $self->{DELAY_TIME} . " seconds");			
			$stock_info_set->{MARKET_INFO}->set('Time', UnixDate($market_time, "%H:%M:%S"));						
		}else{
			$stock_info_set->{MARKET_INFO}->set('Time', undef);			
		}
		# calculate the previous index
		my $changed_percent = $stock_info_set->{MARKET_INFO}->get('ChangePercent');
		if( $changed_percent ne '0' ){
			$stock_info_set->{MARKET_INFO}->set('PrevIndex',sprintf('%0.2f', 100*($stock_info_set->{MARKET_INFO}->get('ChangeIndex') / $changed_percent )));
		}else{
				$stock_info_set->{MARKET_INFO}->set('PrevIndex', 0);
		}
		# set other market infor fields
		$stock_info_set->{MARKET_INFO}->set('CHANNEL_NAME', $stock_info_set->{CHANNEL_INFO}->get('NAME'));
		$stock_info_set->{MARKET_INFO}->set('SYS_SEQ', $stock_info_set->{CHANNEL_INFO}->get('SYS_SEQ'));
		$stock_info_set->{MARKET_INFO}->set('SECURITY_CENTER', $self->{SECURITY_CENTER_CODE});
		
		# process the stock info parts			
		my @stock_infos = split('\|', $content_stock_info);
		foreach my $stock_info_tmp (@stock_infos){
			my $stock_info = StockInfo::new('ObjectInfo');
			my @field_values = split(':', $stock_info_tmp);
			for(my $i =0; $i < @field_values; $i++){
				my $field = $self->{STOCK_FIELD_FORMAT}->[$i];
				if(($field =~ /Best.*Price/) && ($field_values[$i] eq '')){
					$field_values[$i] = '0';
				}
				$field_values[$i] =~ s/,//g;
				if($field =~ /.*Price/ ){
					$field_values[$i] = -1 if($field_values[$i] eq 'ATO');
					$field_values[$i] = -2 if($field_values[$i] eq 'ATC');
				}
				
				if($field ne ''){
					$stock_info->set($self->{STOCK_FIELD_FORMAT}->[$i], $field_values[$i]);
				}
			}
			$stock_info->set('CHANNEL_NAME', $stock_info_set->{CHANNEL_INFO}->get('NAME'));
			$stock_info->set('SYS_SEQ', $stock_info_set->{CHANNEL_INFO}->get('SYS_SEQ'));	
			$stock_info_set->push_stock_info($stock_info);
		}
	}else{ # the content is not in a valid format, set market_info, stock_info_set to undef
		$stock_info_set->{MARKET_INFO} = undef;
		$stock_info_set->{STOCK_INFO_SET} = undef;
	}
	 	
	if(ref($stock_info_set->{MARKET_INFO}) && defined($stock_info_set->stock_infos())){
		$self->{STATUS}->{CODE} = 'SUCCEEDED';
		$self->{STATUS}->{MSG} = 'Parsed successfully ';		
	}else{
		$self->{STATUS}->{CODE} = 'FAILED';
		$self->{STATUS}->{MSG} = 'Failed to parse';		
	}	
	# caculate processing time 
	$proc_time = time - $start_time;
	$stock_info_set->{CHANNEL_INFO}->set('PROCESSING_TIME', $proc_time);
	$stock_info_set->{CHANNEL_INFO}->set('STATUS', $self->{STATUS}->{CODE});
	$stock_info_set->{CHANNEL_INFO}->set('MESSAGE', $self->{STATUS}->{MSG});	
	return ($stock_info_set,$self->{STATUS});
}
##########################
## check market status	##
##########################
sub get_market_status{
	my $self = shift;
	my $market_start_time = shift;
	my $market_stop_time = shift;
	
	my $start_time = time();
	my $content;
	my $is_success;
	my $status_line;
	my $market_status = undef;
		
	# get data source from url 
	($content, $is_success, $status_line) = $self->get_data_source();
	
	if (!$is_success){
		$self->{STATUS}->{CODE} = 'TIMEOUT';
		$self->{STATUS}->{MSG} = 'Can\'t fetch data source(connection timeout)';
		return (undef,$self->{STATUS});			
	}else{
		my @contents = split("^", $content);
		my @market_info = split(':', $contents[0]);
		my $phase = $market_info[0];		
		if($phase > 0 && $phase < 5 ){
			$market_status->{CODE} = 'OPENING';
			$market_status->{MSG} = 'The market was opened and at the phase ' . $phase ;

		}else{
			$market_status->{CODE} = 'CLOSING';
			$market_status->{MSG} = 'The market is closing';
		}
		return $market_status;
	}	
}	
sub DESTROY{
	
} 
1;